//
// This file is part of cpp-lib, a library of C++ functions and classes.
// Cpp-lib is copyright (C) 2004 and onwards, The CPL Interest Group.
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
// General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library (see the file COPYING); if not, write to the
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
// 02111-1307  USA
//
// $Id$
//
// I/O operators.

#ifndef CPP_LIB_MATRIX_IO_H
#define CPP_LIB_MATRIX_IO_H

#include <istream>
#include <ostream>

#include "cpp-lib/matrix.h"

namespace cpl {

namespace math {


///
/// Write in table form (just whitespace between elements, a newline
/// after each row).  For banded matrices, writes only nonzero band.
///
/// Format: 
/// 
/// x( 1 , 1 ) x( 1 , 2 ) ... x( 1 , ub + 1 ) '\n'
/// x( 2 , 1 ) x( 2 , 1 ) ... x( 2 , ub + 2 ) '\n'
///           ...
/// x( lb + 1 , 1 ) x( lb + 1 , 2 ) ...       '\n'
///                 x( lb + 2 , 2 ) ...       '\n'
/// ...
///

template< typename T , typename tag >
std::ostream& operator<<( std::ostream& , matrix< T , tag > const& ) ;

/// Read in row major form; elements must be separated by whitespace.
/// Matrix dimensions must be set before.  For banded matrices, reads
/// only in nonzero band.  See operator<< for format.

template< typename T , typename tag >
std::istream& operator>>( std::istream& , matrix< T , tag >& ) ;


/// Precision for to_file().

enum { MATRIX_PRECISION = 16 } ;


/// Write vector as matrix, optionally transposed.

void to_file(
  std::vector< std::vector< double > > const& v ,
  std::string const& filename ,
  bool transpose
) ;

} // namespace math

} // namespace cpl


//
// Care must be taken here.  There's std::operator<< and
// std::ostream::operator<< (which is preferred if it exists).
//
// std::operator<< may be ambiguated by our own template!
//

template< typename T , typename tag >
std::ostream& cpl::math::operator<<
( std::ostream& os , matrix< T , tag > const& A ) {

  for( long i = 1                     ; i <= A.rows()             ; ++i ) {
  for( long j = first_column( A , i ) ; j <= last_column( A , i ) ; ++j ) {

    if( !os ) { return os ; }
    os << A( i , j ) ;
    if( j < last_column( A , i ) ) { os << ' ' ; }

  }

  os << '\n' ;

  }

  return os ;

}


template< typename T , typename tag >
std::istream& cpl::math::operator>>
( std::istream& is , cpl::math::matrix< T , tag >& A ) {

  for( long i = 1                     ; i <= A.rows()             ; ++i ) {
  for( long j = first_column( A , i ) ; j <= last_column( A , i ) ; ++j ) {

    if( !is ) { return is ; }
    is >> A( i , j ) ;

  }
  }

  return is ;

}


#endif // CPP_LIB_MATRIX_IO_H
